﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Remoting;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GurLoader;
using GurLoader.Preferences;
using GurLoader.Service;
using GurLoader.Service.ImgurTaskBuilder;
using GurLoader.Service.MessageProcessing;
using MailSlot;
using Moq;
using NUnit.Framework;

namespace GurLoaderWPF.Test
{
    [TestFixture]
    public class ListenerLoopTests
    {
        [Test]
        public void CreateInstanceTest()
        {
            GurLoaderPreferences prefs = new GurLoaderPreferences();
            Mock<MessageProcessingService> mockMessageProcessingService = new Mock<MessageProcessingService>();
            Mock<IAppConfiguration> mockAppConfig = new Mock<IAppConfiguration>();

            var instance = new ListenerLoop(prefs, mockMessageProcessingService.Object, mockAppConfig.Object);
            Assert.IsNotNull(instance);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateInstanceNullPreferencesTest()
        {
            Mock<MessageProcessingService> mockMessageProcessingService = new Mock<MessageProcessingService>();
            Mock<IAppConfiguration> mockAppConfig = new Mock<IAppConfiguration>();

            var instance = new ListenerLoop(null, mockMessageProcessingService.Object, mockAppConfig.Object);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateInstanceNullMessageServiceTest()
        {
            GurLoaderPreferences prefs = new GurLoaderPreferences();
            Mock<IAppConfiguration> mockAppConfig = new Mock<IAppConfiguration>();

            var instance = new ListenerLoop(prefs, null, mockAppConfig.Object);
        }

        [Test]
        [ExpectedException(typeof (ArgumentNullException))]
        public void CreateInstanceNullAppConfigTest()
        {
            GurLoaderPreferences prefs = new GurLoaderPreferences();
            Mock<MessageProcessingService> mockMessageProcessingService = new Mock<MessageProcessingService>();

            var instance = new ListenerLoop(prefs, mockMessageProcessingService.Object, null);
        }

        [Test]
        public void ProcessCommandTest()
        {            
            GurLoaderPreferences prefs = new GurLoaderPreferences();
            Mock<MessageProcessingService> mockMessageProcessingService = new Mock<MessageProcessingService>();
            Mock<IAppConfiguration> mockAppConfig = new Mock<IAppConfiguration>();

            string mailslotName = "testMailbox";
            NameValueCollection nvCollection = new NameValueCollection();
            nvCollection.Add("mailboxName", mailslotName);
            mockAppConfig.Setup(x => x.Settings).Returns(nvCollection);

            string command = "SendImages C:\\test.jpg";

            var instance = new ListenerLoop(prefs, mockMessageProcessingService.Object, mockAppConfig.Object);
            Assert.IsNotNull(instance);

            ManualResetEvent mreCommandPrepared = new ManualResetEvent(false);
            instance.CommandPrepared += (sender, e) =>
            {
                mreCommandPrepared.Set();
            };

            ManualResetEvent mreListenerStarted = new ManualResetEvent(false);
            instance.ListenerStarted += (sender, e) => mreListenerStarted.Set();

            instance.Start();

            Assert.IsTrue(mreListenerStarted.WaitOne(1000 * 5), "Timeout waiting for listener to start.");

            mockMessageProcessingService
                .Setup(x=>x.ProcessMessage<ImgurProcessResult>( 
                        command, 
                        It.IsAny<Progress<IDelegatingCommandProgress>>(), 
                        It.IsAny<CancellationToken>() ))
                .Returns(new Task<ImgurProcessResult>(() => null))
                .Verifiable();


            
            MailslotClient client = new MailslotClient(mailslotName);
            client.SendMessage(command);
    
            Assert.IsTrue(mreCommandPrepared.WaitOne(1000*5), "Timeout waiting for command prepared callback.");

            mockMessageProcessingService
                .Verify(x => x.ProcessMessage<ImgurProcessResult>(
                    command,
                    It.IsAny<Progress<IDelegatingCommandProgress>>(),
                    It.IsAny<CancellationToken>()), Times.Once);
        }
    }
}
